package com.xlh.service.course.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.xlh.dao.course.CourseBasicMapper;
import com.xlh.dao.course.CourseMapper;
import com.xlh.dao.course.CourseSortMapper;
import com.xlh.dao.course.CourseTeacherMapper;
import com.xlh.dao.course.ext.CourseMapperExt;
import com.xlh.dao.course.ext.CourseSortMapperExt;
import com.xlh.dao.course.ext.CourseTeacherMapperExt;
import com.xlh.dto.cases.BusinessDTO;
import com.xlh.dto.course.*;
import com.xlh.dto.system.ResourceRelationDTO;
import com.xlh.dto.system.ValueDTO;
import com.xlh.dto.user.ClassCourseDTO;
import com.xlh.dto.user.ClassDTO;
import com.xlh.dto.user.CourseClassDTO;
import com.xlh.dto.user.UserInfoDTO;
import com.xlh.enums.*;
import com.xlh.enums.course.*;
import com.xlh.enums.courseTest.CheckEnum;
import com.xlh.enums.courseTest.ReportTypeEnum;
import com.xlh.enums.user.IdentityEnum;
import com.xlh.enums.user.RoleEnum;
import com.xlh.exception.DeleteDealOperatingException;
import com.xlh.exception.DownloadFileException;
import com.xlh.exception.common.BadRequestException;
import com.xlh.exception.common.GlobalException;
import com.xlh.exception.common.NotFoundException;
import com.xlh.param.course.CourseParam;
import com.xlh.param.course.CreateOrUpdateCourseSortParam;
import com.xlh.param.course.CreateResourceParam;
import com.xlh.param.course.FileParam;
import com.xlh.pojo.course.*;
import com.xlh.pojo.problem.PcConfig;
import com.xlh.pojo.system.*;
import com.xlh.pojo.user.Class;
import com.xlh.pojo.user.ClassCourse;
import com.xlh.security.UserInfoHolder;
import com.xlh.service.MdHtmlFileService;
import com.xlh.service.cases.BusinessCaseService;
import com.xlh.service.check.CheckService;
import com.xlh.service.course.ChapterService;
import com.xlh.service.course.CourseService;
import com.xlh.service.course.DirectionService;
import com.xlh.service.course.TechnologyService;
import com.xlh.service.courseTest.ExperimentService;
import com.xlh.service.courseTest.PaperAnswerSheetService;
import com.xlh.service.courseTest.PaperService;
import com.xlh.service.courseTest.PracticeService;
import com.xlh.service.problem.ProblemCommunicationService;
import com.xlh.service.system.SystemConfigService;
import com.xlh.service.system.SystemResourceService;
import com.xlh.service.user.ClassService;
import com.xlh.service.user.UserService;
import com.xlh.util.BeanUtil;
import com.xlh.util.ExcelsUtil;
import com.xlh.virtualization.constant.ContextTypeEnum;
import com.xlh.virtualization.service.ExperimentStatisticService;
import com.xlh.virtualization.service.ImageService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 课程
 * <p>
 * Created by lx on 2019/1/28.
 */
@Service
public class CourseServiceImpl implements CourseService {

    private static Logger LOGGER = LoggerFactory.getLogger(CourseServiceImpl.class);

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private CourseBasicMapper courseBasicMapper;

    @Autowired
    private CourseMapperExt courseMapperExt;

    @Autowired
    private CourseTeacherMapper courseTeacherMapper;

    @Autowired
    private CourseTeacherMapperExt courseTeacherMapperExt;

    @Autowired
    private CourseSortMapper courseSortMapper;

    @Autowired
    private CourseSortMapperExt courseSortMapperExt;

    @Autowired
    private ClassService classService;

    @Autowired
    private SystemConfigService configService;

    @Autowired
    private SystemResourceService resourceService;

    @Autowired
    private MdHtmlFileService mdHtmlFileService;

    @Autowired
    private UserService userService;

    @Autowired
    private ExperimentStatisticService experimentStatisticService;

    @Autowired
    private UserInfoHolder userInfoHolder;

    @Autowired
    private BusinessCaseService businessCaseService;

    @Autowired
    private TechnologyService technologyService;

    @Autowired
    private ChapterService chapterService;

    @Autowired
    private PaperService paperService;

    @Autowired
    private ImageService imageService;

    @Autowired
    private PracticeService practiceService;

    @Autowired
    private ExperimentService experimentService;

    @Autowired
    private PaperAnswerSheetService paperAnswerSheetService;

    @Autowired
    private ProblemCommunicationService problemCommunicationService;

    @Autowired
    private DirectionService directionService;

    @Autowired
    private SystemResourceService systemResourceService;

    @Autowired
    private CheckService checkService;

    @Override
    public CourseBasicDTO getCourse(Long courseId) {
        List<CourseBasicDTO> courseBasics = listCourse(
                Lists.newArrayList(courseId), null, null, null);
        if (CollectionUtils.isEmpty(courseBasics)) {
            throw new NotFoundException("暂无课程信息");
        }

        CourseBasicDTO course = courseBasics.get(0);
        ImageLoadTypeEnum imageLoadTypeEnum = ImageLoadTypeEnum.getByCode(course.getImageLoadType());
        course.setImageLoadTypeStr(imageLoadTypeEnum == null ? null : imageLoadTypeEnum.getMessage());
        course.setDirection(convertCourseDirection(courseId));

        return course;
    }

    @Override
    public List<CourseBasicDTO> listCourse(List<Long> courseIds, Boolean ownCourse, Boolean preseted, Integer status) {
        List<CourseBasicDTO> course = listCourse(
                courseIds, ownCourse, preseted, status, null, null);
        return convert(course);
    }

    @Override
    public List<CourseBasicDTO> listCourse(
            List<Long> courseIds, Boolean ownCourse, Boolean preseted, Integer status,
            List<String> names, List<Long> courseBasicIds) {
        return courseMapperExt.getCourse(
                courseIds, ownCourse, preseted, status, names, courseBasicIds);
    }

    @Override
    public List<CourseDTO> listCourse(
            List<Integer> statusList, Boolean preseted, Boolean ownCourse, List<Long> userIds, List<Long> courseIds) {
        return courseMapperExt.listCourse(statusList, preseted, ownCourse, userIds, courseIds);
    }

    @Override
    public Course getCourseById(Long courseId) {
        Course course = courseMapper.selectByPrimaryKey(courseId);
        if (course == null) {
            throw new NotFoundException("暂无课程信息");
        }
        return course;
    }

    @Override
    public List<UserInfoDTO> getCourseTeachers(Long courseId, Long classId) {

        // 如果当前是学生，需要查询学生的班级id
        if (userInfoHolder.isStudent()) {
            List<Long> classIds = classService.queryStudentClass(courseId, null);
            classId = classId == null ? CollectionUtils.isEmpty(classIds) ? null : classIds.get(0) : classId;
        }

        List<Long> userIds = getCourseTeacherIds(courseId, classId);

        // 获取用户信息
        List<UserInfoDTO> result = Lists.newArrayList();
        Map<Long, UserInfoDTO> userInfoMap = getUserInfo(userIds);
        if (MapUtils.isEmpty(userInfoMap)) return result;
        userIds.forEach(userId -> {
            UserInfoDTO userInfoDTO = userInfoMap.get(userId);
            result.add(userInfoDTO == null ? new UserInfoDTO() : userInfoDTO);
        });

        // 若是学生，需要展示班级名称
        if (userInfoHolder.isStudent() && classId != null) {
            List<Class> classes = classService.listClass(Lists.newArrayList(classId), false);
            if (CollectionUtils.isNotEmpty(classes)) {
                result.get(0).setStudentClassName(classes.get(0).getName());
                result.get(0).setClassId(classId);
            }
        }

        return result;
    }

    @Override
    public List<Long> getCourseTeacherIds(Long courseId, Long classId) {
        Course course = getCourseById(courseId);

        // 教师
        List<Long> userIds = Lists.newArrayList(course.getUserId());

        // 助教
        List<CourseTeacher> courseTeachers = queryCourseTeacher(Lists.newArrayList(courseId), null, classId);
        List<Long> assistantUserIds = courseTeachers.stream()
                .map(CourseTeacher::getUserId).collect(Collectors.toList());

        if (userInfoHolder.isTeacher()
                && (userIds.contains(userInfoHolder.getUserId())
                || assistantUserIds.contains(userInfoHolder.getUserId()))) {
            userIds.add(userInfoHolder.getUserId());
        }

        // 合并
        userIds.addAll(assistantUserIds);
        return userIds.stream().distinct().collect(Collectors.toList());
    }

    @Override
    public CourseIndexDTO getCourseIndex(
            Integer coursePageSize, Integer skillPageSize, Integer casePageSize, Integer technologyPageSize) {

        // 获取课程信息
        List<CourseIndexInfoDTO> data = getIndexData();

        Long userId = userInfoHolder.isLogin() ? userInfoHolder.getUserId() : null;
        CourseIndexDTO indexDTO = new CourseIndexDTO();

        // 获取配置基本信息
        String skillKey = SystemConfigEnum.INDEX_SKILL.getKey();
        String businessKey = SystemConfigEnum.BUSINESS_SHOW.getKey();
        String technologyKey = SystemConfigEnum.TECHNOLOGY_SHOW.getKey();
        String schoolKey = SystemConfigEnum.SCHOOL_TYPE.getKey();
        Map<String, List<ValueDTO>> keyMap = configService.listConfigByKey(
        Lists.newArrayList(skillKey, businessKey, technologyKey, schoolKey));

        if (MapUtils.isNotEmpty(keyMap)) {
            List<ValueDTO> configs = keyMap.get(schoolKey);
            if (CollectionUtils.isNotEmpty(configs)) {
                // 转换互联网版本课程专业方向
                convertDirectionData(
                        CollectionUtils.isEmpty(data) ?
                                null : data.stream().map(CourseIndexInfoDTO::getId).collect(Collectors.toList()),
                        CollectionUtils.isEmpty(data) ?
                                null : data.stream().filter(courseIndexInfoDTO -> !courseIndexInfoDTO.getPreseted()
                                && CollectionUtils.isNotEmpty(courseIndexInfoDTO.getUserIds())
                                && courseIndexInfoDTO.getUserIds().contains(userId))
                                .map(CourseIndexInfoDTO::getId).collect(Collectors.toList()),
                        indexDTO, configs);

            }
        }

        // 转换首页数据格式
        convertCourseIndexDTO(coursePageSize, data, indexDTO);

        // 转换统计
        convertStatistics(data, indexDTO);

        if (MapUtils.isNotEmpty(keyMap)) {
            if (CollectionUtils.isNotEmpty(keyMap.get(skillKey))
                    && Objects.equals(keyMap.get(skillKey).get(0).getKeyValue(), "1")) {
                // 调用接口岗位信息
                convertSkillDTO(skillPageSize, indexDTO);
            }

            if (CollectionUtils.isNotEmpty(keyMap.get(businessKey))
                    && Objects.equals(keyMap.get(businessKey).get(0).getKeyValue(), "1")) {
                // 调用接口获取案例库信息
                convertBusinessDTO(casePageSize, indexDTO);
            }

            if (CollectionUtils.isNotEmpty(keyMap.get(technologyKey))
                    && Objects.equals(keyMap.get(technologyKey).get(0).getKeyValue(), "1")) {
                // 调用接口获取技术库信息
                convertTechnologyDTO(technologyPageSize, indexDTO);
            }

        }

        // 获取用户信息
        if (userInfoHolder.isLogin()) {
            String name = StringUtils.isBlank(userInfoHolder.getUser().getName()) ?
                    "" : StrUtil.sub(userInfoHolder.getUser().getName(), 0, 1);
            String str = IdentityEnum.getByRole(userInfoHolder.getUser().getRole()) == IdentityEnum.STUDENT ?
                    "同学" : "老师";
            indexDTO.setUserName(name + str);
        }
        return indexDTO;
    }

    @Override
    public CourseIndexDataDTO getCourseDirectionIndex(Integer coursePageSize, Long directionId) {

        List<Direction> directionList = directionService.queryDirection(Lists.newArrayList(directionId));
        if (CollectionUtils.isEmpty(directionList)) throw new NotFoundException("");

        // 获取课程信息 核心课程、扩展课程
        List<CourseIndexInfoDTO> data = getIndexData();

        if (CollectionUtils.isEmpty(data)) {
            return new CourseIndexDataDTO();
        }

        // 配置图标放置到结果集中
        data = configService.convertIcon(data, LocalResourcesEnum.SYSTEM_FILE);

        // 获取教师信息
        Map<Long, UserInfoDTO> userInfoMap = getUserMap(data);

        // 查询课程类型
        List<CourseExtend> courseExtends = directionService.queryCourseExtend(
                Lists.newArrayList(directionId),
                data.stream().map(CourseIndexInfoDTO::getId).collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(courseExtends)) {
            return new CourseIndexDataDTO();
        }

        // 将所有课程进行过滤，只获取部分课程
        List<Long> courseIds = courseExtends.stream().map(CourseExtend::getCourseId).collect(Collectors.toList());
        data = data.stream()
                .filter(courseIndexInfoDTO -> courseIds.contains(courseIndexInfoDTO.getId()))
                .collect(Collectors.toList());

        // 当用户登陆的时候
        if (userInfoHolder.isLogin() && CollectionUtils.isNotEmpty(courseIds)) {
            List<Permission> permissions = userService.queryUserPermission(userInfoHolder.getUserId());
            if (CollectionUtils.isNotEmpty(permissions)) {
                List<Integer> status = permissions.stream().map(Permission::getStatus).collect(Collectors.toList());
                if (!status.contains(directionList.get(0).getType())) {
                    // 只保留自己的课程
                    data = data.stream().filter(courseIndex -> !courseIndex.getPreseted()
                            && courseIndex.getUserIds().contains(userInfoHolder.getUserId())
                            && courseIds.contains(courseIndex.getId())).collect(Collectors.toList());
                }

            }
        }

        // 转换
        return convert(userInfoHolder.isLogin(), userInfoMap, coursePageSize, data);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createCourse(CourseParam param) {

        // 检查创建课程的参数是否正确
        checkCreateCourseParam(param, null);

        // 将参数转换为CourseBasic数据 并插入数据库
        CourseBasic courseBasic = convertCourseParam(param);

        Course course = new Course();
        course.setUserId(userInfoHolder.getUserId());
        Long courseId = createCourse(courseBasic, course);

        // 添加课程方向
        directionService.createCourseExtend(Lists.newArrayList(courseId), param.getDirectionIds());

        return courseId;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createCourse(CourseBasic courseBasic, Course course) {
        if (courseBasic == null || course == null) return null;
        courseBasicMapper.insertSelective(courseBasic);
        convertCourse(course, courseBasic.getId());
        courseMapper.insertSelective(course);
        return course.getId();
    }

    @Override
    public Long createCourse(Long courseId, Long userId) {
        Course course = courseMapper.selectByPrimaryKey(courseId);
        course.setId(null);
        course.setDeleted(false);
        course.setOwnCourse(false);
        course.setUserId(userId);
        courseMapper.insertSelective(course);
        return course.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCourse(Long courseId, CourseParam param) {

        // 检查参数并获取课程
        CourseDTO courseDTO = checkParamAndGetCourse(param, courseId);


        // 转换数据
        CourseBasic data = BeanUtil.transform(CourseBasic.class, param);

        // 自己的课程：修改数据库数据；不是自己的课程，需要创建course_basic表
        if (courseDTO.getOwnCourse()) {
            CourseBasic courseBasic = getCourseBasic(courseDTO.getCourseBasicId());
            convertCourseBasic(courseBasic, data);
            courseBasicMapper.updateByPrimaryKey(courseBasic);
        } else {
            data.setPreseted(userInfoHolder.isAdmin() ? true : false);
            courseBasicMapper.insertSelective(data);

            // 修改course表
            Course course = new Course();
            course.setId(courseId);
            course.setCourseBasicId(data.getId());
            course.setOwnCourse(true);
            courseMapper.updateByPrimaryKeySelective(course);
        }

        // 获取所有引用这门课的课程
        List<Course> courses = queryCourses(Lists.newArrayList(courseId));

        // 删除课程额外信息 再 插入课程额外信息
        directionService.deleteCourseExtend(
                null, courses.stream().map(Course::getId).collect(Collectors.toList()));
        directionService.createCourseExtend(
                courses.stream().map(Course::getId).collect(Collectors.toList()), param.getDirectionIds());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCourse(CourseBasic courseBasic) {
        courseBasicMapper.updateByPrimaryKeySelective(courseBasic);
    }

    @Override
    public void updateCourseBasicResource(Long courseBasicId, Long resourceId) {
        CourseBasic courseBasic = courseBasicMapper.selectByPrimaryKey(courseBasicId);
        courseBasic.setResourceId(resourceId);
        courseBasicMapper.updateByPrimaryKey(courseBasic);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCourseStatus(Long courseId, CourseStatusEnum statusEnum) {

        /**
         * 修改内容：
         * 1. 直接将课程改为已发布
         * 2. 发布镜像
         */

        // 检查是否是本人的课程操作，不是本人操作不能修改
        CourseDTO courseDTO = checkAndGetCourse(courseId);
        if (statusEnum == null) throw new BadRequestException();

        // 修改课程状态
        CourseBasic courseBasic = new CourseBasic();
        courseBasic.setId(courseDTO.getCourseBasicId());
        courseBasic.setStatus(statusEnum.getCode());
        updateCourse(courseBasic);

        // 设置发布课程
        if (statusEnum == CourseStatusEnum.SHARED) {
            // 发布镜像
            imageService.updateSharedStatusByContext(ContextTypeEnum.TASK.getCode(), courseId, true);
        }

        if (statusEnum == CourseStatusEnum.SAVE) {
            // 取消镜像
            imageService.updateSharedStatusByContext(ContextTypeEnum.TASK.getCode(), courseId, false);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatchCourse(List<Long> courseIds, Boolean errorDealFlag,
                                  Boolean logicDeleted, Boolean updatePreseted) {

        /**
         * 删除内容：
         * 1. 走批量删除章节的接口 -> 相当于章节信息、虚机等信息都删除
         * 2. 考试答题情况、出题情况、考试试卷
         * 3. 删除班级接口 -> 相当于删除班级、删除学生
         * 4. 删除课程基本信息
         */

        // 检查是否允许删除 并获取最终的课程id集合
        courseIds = checkDeleteParamAndGet(courseIds, errorDealFlag);
        if (CollectionUtils.isEmpty(courseIds)) throw new BadRequestException();

        // 获取非预置，自己创建的课程。 删除的数据需要抛出自己自定义的课程
        List<CourseBasicDTO> courseList = courseMapperExt.getCourse(courseIds, true, false,
                null, null, null);
        List<Long> ownCourseIds = courseList.stream().map(CourseBasicDTO::getId).collect(Collectors.toList());
        List<Long> finalOwnCourseIds = ownCourseIds;
        List<Long> deleteIds = courseIds.stream()
                .filter(courseId -> !finalOwnCourseIds.contains(courseId)).collect(Collectors.toList());
        if (updatePreseted == null || !updatePreseted) {
            deleteIds.addAll(ownCourseIds);
            ownCourseIds = Lists.newArrayList();
        }

        // 删除章节及资源、资源权限、学生/教师 已学过、删除笔记、虚机、镜像私有删除
        List<String> fileNames = chapterService.deleteChapter(
                deleteIds, null, logicDeleted, false, null);
        if (CollectionUtils.isNotEmpty(ownCourseIds)) {
            List<String> ownCourseFileNames = chapterService.deleteChapter(
                    ownCourseIds, null, logicDeleted, false, updatePreseted);
            fileNames = CollectionUtils.isEmpty(fileNames) ? Lists.newArrayList() : fileNames;
            fileNames.addAll(CollectionUtils.isEmpty(ownCourseFileNames) ? Lists.newArrayList() : ownCourseFileNames);
        }

        // 删除试卷（同时删除试卷题目、答案、答题卡）
        paperService.deletePaper(courseIds);

        // 删除班级
        courseIds.forEach(courseId -> {
            // 获取该课程下的班级列表
            List<ClassCourse> classCourses = classService.listClassCourse(courseId, false);
            if (CollectionUtils.isNotEmpty(classCourses)) {
                classService.deleteBatchClass(courseId,
                        classCourses.stream().map(ClassCourse::getClassId).collect(Collectors.toList()),
                        errorDealFlag, logicDeleted);
            }

        });

        // 资源权限
        chapterService.deleteResourceAuthority(AuthorityOperatingTypeEnum.COURSE, courseIds);

        if (updatePreseted != null && updatePreseted && CollectionUtils.isNotEmpty(ownCourseIds)) {
            // 修改为自己的课程
            courseList.forEach(courseBasicDTO -> {
                Course course = new Course();
                course.setId(courseBasicDTO.getId());
                course.setUserId(1L);
                courseMapper.updateByPrimaryKeySelective(course);

                CourseBasic courseBasic = new CourseBasic();
                courseBasic.setId(courseBasicDTO.getCourseBasicId());
                courseBasic.setStatus(CourseStatusEnum.SHARED.getCode());
                courseBasic.setPreseted(true);
                courseBasicMapper.updateByPrimaryKeySelective(courseBasic);
            });
        }

        if ((updatePreseted == null || !updatePreseted) && CollectionUtils.isNotEmpty(deleteIds)) {
            // 删除课程 以及 预置资源
            List<String> deleteResource = deleteCourseAndCourseBasic(deleteIds, logicDeleted, false);
            if (CollectionUtils.isNotEmpty(deleteResource)) {
                fileNames = CollectionUtils.isEmpty(fileNames) ? Lists.newArrayList() : fileNames;
                fileNames.addAll(deleteResource);
            }

            // 删除课程资源
            List<String> deleteCourseResource = deleteCourseResource(
                    deleteIds, Lists.newArrayList(ResourcesTypeEnum.COURSE_OUTLINE),
                    ResourceRelationTypeEnum.COURSE, false);
            if (CollectionUtils.isNotEmpty(deleteCourseResource)) {
                fileNames = CollectionUtils.isEmpty(fileNames) ? Lists.newArrayList() : fileNames;
                fileNames.addAll(deleteCourseResource);
            }

            // 批量删除课程分类
            deleteCourseSort(null, deleteIds);
        }

        // 删除章节资源
        chapterService.deleteStaticResources(fileNames);

    }

    @Override
    public List<CourseDTO> listCourse(CourseSharedEnum courseSharedEnum) {
        Boolean preseted = null;
        switch (courseSharedEnum) {
            case PRESET:
                preseted = true;
                break;
            case OTHER:
                preseted = false;
                break;
        }
        return listCourse(Lists.newArrayList(CourseStatusEnum.SHARED.getCode()),
                preseted, true, null, null);
    }

    @Override
    public List<Course> queryCourses(List<Long> courseIds) {
        return courseMapperExt.queryCourses(courseIds);
    }

    @Override
    public List<CourseDTO> queryCourseList() {
        List<CourseDTO> courseDTOS = null;
        if (userInfoHolder.isAdmin()) {
            List<CourseBasicDTO> courseBasics = listCourse(
                    null, true, true, CourseStatusEnum.SHARED.getCode());
            courseDTOS = BeanUtil.batchTransform(CourseDTO.class, courseBasics);
        }
        if (userInfoHolder.isTeacher()) {
            courseDTOS = queryTeacherCourse(userInfoHolder.getUserId());
        }
        return convertCourseDTO(courseDTOS);
    }

    @Override
    public String checkAndGetFilePath(Integer type, FileParam param) {

        // 检查
        if (param == null || StringUtils.isBlank(param.getRemark()) || StringUtils.isBlank(param.getFileName())) {
            throw new BadRequestException();
        }

        // 获取资源
        List<Resource> resources = chapterService.getResource(type, param.getFileName(), param.getRemark());
        if (CollectionUtils.isEmpty(resources)) {
            throw new DownloadFileException("暂无预置资源");
        }

        // 获取本地资源是否存在
        String filePath = LocalResourcesEnum.COURSE.getLocalUploadPath(
                new String[]{String.valueOf(resources.get(0).getRemark())}, resources.get(0).getFileName());
        if (!FileUtil.exist(filePath)) {
            throw new DownloadFileException("暂无资源");
        }

        // 根据资源获取课程名称
        CourseBasicExample example = new CourseBasicExample();
        example.createCriteria().andResourceIdEqualTo(resources.get(0).getId());
        List<CourseBasic> courseBasics = courseBasicMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(courseBasics)) {
            throw new GlobalException("");
        }

        String fileName = StringUtils.join(
                courseBasics.get(0).getName(),
                "-",
                ResourcesTypeEnum.PRESET_RESOURCE.getMessage(),
                ".",
                StrUtil.subAfter(param.getFileName(), ".", true)
        );
        param.setDownloadFileName(fileName);

        return filePath;
    }

    @Override
    public List<CourseDTO> getCourseInfo(List<Long> courseIds) {
        // 教师：创作或从其他教师/管理员拖拽过来的。所以预置及自己课程字段为null ；管理员：可以修改其他管理员课程信息，所以userId为null；
        List<CourseDTO> courseDTOS = listCourse(
                Lists.newArrayList(CourseStatusEnum.SHARED.getCode(), CourseStatusEnum.SAVE.getCode()),
                null, null, null, courseIds);
        if (CollectionUtils.isEmpty(courseDTOS)) {
            throw new GlobalException("课程不存在");
        }

        return courseDTOS;
    }

    @Override
    public Long queryExistCourseId(Long courseBasicId, Long userId) {
        CourseExample example = new CourseExample();
        example.createCriteria()
                .andCourseBasicIdEqualTo(courseBasicId)
                .andUserIdEqualTo(userId)
                .andDeletedEqualTo(false);
        List<Course> courses = courseMapper.selectByExample(example);
        return CollectionUtils.isEmpty(courses) ? null : courses.get(courses.size() - 1).getId();
    }

    @Override
    public List<Long> checkDeleteParamAndGet(List<Long> courseIds, Boolean errorDealFlag) {

        /**
         * 提示信息判断内容：
         * 1. 教师下有学生
         * 2. 教师正在给学生考试
         * 3. 教师创作的课程是否被其他教师占用
         */

        if (CollectionUtils.isEmpty(courseIds)) throw new BadRequestException();

        // 获取数据库存在的课程信息
        List<CourseDTO> courseInfo = getCourseInfo(courseIds);

        // 获取数据库存在的课程id集合
        courseIds = courseInfo.stream().map(CourseDTO::getId).distinct().collect(Collectors.toList());

        // 获取其他教师占用课程数据，如果存在就放置到课程集合中
        List<Long> occupyCourseIds = getOccupyCourseId(courseInfo);
        if (CollectionUtils.isNotEmpty(occupyCourseIds)) {
            courseIds.addAll(occupyCourseIds);
        }

        // 获取课程下的学生数据
        List<CourseClassDTO> courseClassDTOS = classService.queryUserClass(courseIds);

        // 课程是否考试
        List<Long> testingCourseIds = paperService.queryTestingCourseIds(courseIds);

        // 如果无报错处理并且 教师被占用 或者 有学生数据，就提示错误信息
        if (errorDealFlag == null
                && (CollectionUtils.isNotEmpty(occupyCourseIds)
                || CollectionUtils.isNotEmpty(courseClassDTOS) || CollectionUtils.isNotEmpty(testingCourseIds))) {
            List<String> list = Lists.newArrayList();
            if (CollectionUtils.isNotEmpty(courseClassDTOS) || CollectionUtils.isNotEmpty(occupyCourseIds)) {
                list.add("及其他授课教师课程中所有关于该课程的班级、学生、学习记录将被删除");
            }
            if (CollectionUtils.isNotEmpty(testingCourseIds)) {
                list.add("该课程正在考试");
            }
            throw new DeleteDealOperatingException("教师课程中" + StringUtils.join(list, "且"));
        }
        return courseIds;

    }

    @Override
    public UserCourseStatusEnum queryUserCourseStatus(Long id) {
        if (userInfoHolder.isStudent()) {
            // 查当前课程 是 未添加 、 已添加 、已结课
            List<ClassCourse> classCourses = classService.listClassCourse(id, false);
            List<Long> classIds = classCourses.stream()
                    .map(ClassCourse::getClassId).distinct().collect(Collectors.toList());
            List<Long> studentClassIds = userInfoHolder.getStudentClassIds();
            if (!CollectionUtils.containsAny(classIds, studentClassIds)) {
                return UserCourseStatusEnum.NOT_CREATE_CLASS;
            }
            if (classCourses.stream()
                    .filter(classCourse -> studentClassIds.contains(classCourse.getClassId())
                            && !classCourse.getEnded())
                    .count() == 0) {
                return UserCourseStatusEnum.STUDENT_ENDED;
            }
        }

        if (userInfoHolder.isTeacher()) {
            // 获取课程的教师信息
            List<Long> userIds = getCourseTeacherIds(id, null);

            // 获取教师的班级信息
            List<ClassDTO> classDTOS = classService.listClassCourse(
                    id, userInfoHolder.getUserId(), null, null, null);

            if (!userIds.contains(userInfoHolder.getUserId()) || classDTOS == null) {
                return UserCourseStatusEnum.NOT_CREATE_CLASS;
            }
        }

        return UserCourseStatusEnum.EXIST_CLASS;
    }

    @Override
    public List<CourseNavigationDTO> getUserNavigation(Long id) {

        // 获取用户的全部导航
        List<CourseNavigationEnum> userNavigationEnums = CourseNavigationEnum.getUserNavigationEnum(userInfoHolder);

        // 获取用户课程的状态
        UserCourseStatusEnum userCourseStatusEnum = queryUserCourseStatus(id);

        // 交流
        PcConfig pcConfig = problemCommunicationService.getProblemSwitch(id);
        Boolean problemSwitch = pcConfig == null ? false : pcConfig.getPcSwitch();

        List<CourseNavigationDTO> result = Lists.newArrayList();
        switch (userCourseStatusEnum) {
            case NOT_CREATE_CLASS:
                userNavigationEnums.forEach(courseNavigationEnum -> {
                    CourseNavigationDTO courseNavigationDTO = new CourseNavigationDTO(
                            courseNavigationEnum.getMessage(), false, "加入班级后可查看");
                    if (courseNavigationEnum == CourseNavigationEnum.DETAIL) {
                        courseNavigationDTO.setShowed(true);
                        courseNavigationDTO.setHideDescription("");
                    }
                    result.add(courseNavigationDTO);
                });
                break;
            case EXIST_CLASS:
                userNavigationEnums.forEach(courseNavigationEnum -> {
                    CourseNavigationDTO courseNavigationDTO = new CourseNavigationDTO(
                            courseNavigationEnum.getMessage(), true, "");
                    if (courseNavigationEnum == CourseNavigationEnum.COMMUNICATE
                            && userInfoHolder.isStudent() && !problemSwitch) {
                        courseNavigationDTO.setShowed(false);
                        courseNavigationDTO.setHideDescription("教师未开启交流模块");
                    }
                    result.add(courseNavigationDTO);
                });
                break;
            case STUDENT_ENDED:
                userNavigationEnums.forEach(courseNavigationEnum -> {
                    CourseNavigationDTO courseNavigationDTO = new CourseNavigationDTO(
                            courseNavigationEnum.getMessage(), true, "");
                    if (courseNavigationEnum == CourseNavigationEnum.COMMUNICATE
                            && userInfoHolder.isStudent() && !problemSwitch) {
                        courseNavigationDTO.setShowed(false);
                        courseNavigationDTO.setHideDescription("教师未开启交流模块");
                    }
                    if (courseNavigationEnum == CourseNavigationEnum.TEST) {
                        courseNavigationDTO.setShowed(false);
                        courseNavigationDTO.setHideDescription("已结课不可查看");
                    }
                    result.add(courseNavigationDTO);
                });
                break;
        }

        return result;
    }

    @Override
    public Map<Long, Boolean> getStudentIsTesting(List<Long> courseIds) {

        Map<Long, Boolean> resultMap = Maps.newHashMap();

        if (!userInfoHolder.isStudent()) return null;

        List<ClassCourseDTO> classCourseDTOS = classService.listClassCourse(courseIds, false);
        List<Long> studentClassIds = userInfoHolder.getStudentClassIds();

        if (CollectionUtils.isNotEmpty(classCourseDTOS) && CollectionUtils.isNotEmpty(studentClassIds)) {

            classCourseDTOS = classCourseDTOS.stream()
                    .filter(classCourseDTO -> studentClassIds.contains(classCourseDTO.getId()))
                    .collect(Collectors.toList());

            if (CollectionUtils.isEmpty(classCourseDTOS)) return resultMap;

            // 转换参数，为调用后面的方法做准备
            List<com.xlh.dto.courseTest.CourseClassDTO> list = Lists.newArrayList();
            classCourseDTOS.forEach(classCourseDTO -> {
                list.add(new com.xlh.dto.courseTest.CourseClassDTO(
                        classCourseDTO.getCourseId(), classCourseDTO.getId()));
            });

            // 课程是否考试
            List<com.xlh.dto.courseTest.CourseClassDTO> data = paperService.getCourseClassPaper(list);

            if (CollectionUtils.isEmpty(data)) return resultMap;

            // 赋值
            data.forEach(courseClassDTO -> resultMap.put(courseClassDTO.getCourseId(), true));

        }

        return resultMap;
    }

    @Override
    public void createOrUpdatePresetResource(Long id) {

        List<CourseDTO> courseDTOS = listCourse(
                null, null, null, null, Lists.newArrayList(id));
        if (CollectionUtils.isEmpty(courseDTOS)) {
            throw new GlobalException("课程不存在");
        }

        // 插入/修改/删除资源表
        Long resourceId = courseDTOS.get(0).getResourceId();
        try {
            resourceId = chapterService.createOrUpdateResource(id, resourceId);
        } catch (Exception e) {
            if (resourceId != null) {
                List<Resource> resources = resourceService.queryResource(Lists.newArrayList(resourceId));
                resourceService.deleteBatch(resources.stream().map(Resource::getId).collect(Collectors.toList()));
                resourceId = null;
            }
            throw e;
        } finally {
            // 基本表进行修改
            updateCourseBasicResource(courseDTOS.get(0).getCourseBasicId(), resourceId);
        }

    }

    @Override
    public List<CourseDTO> listRelationCourseForStudent(List<Long> classIds) {
        if (CollectionUtils.isEmpty(classIds)) return Lists.newArrayList();
        List<CourseDTO> courseDTOS = courseMapperExt.listRelationCourseForStudent(classIds);
        if (CollectionUtils.isEmpty(courseDTOS)) return courseDTOS;

        // 获取主讲、助教
        List<CourseTeacher> dbCourseTeachers = courseTeacherMapperExt.queryCourseTeacher(
                courseDTOS.stream().collect(Collectors.toMap(CourseDTO::getId, CourseDTO::getClassId)));
        Map<Long, List<CourseTeacher>> courseTeacherMap = BeanUtil.aggByKeyToList("courseId", dbCourseTeachers);

        // 拼接
        convert(courseDTOS, courseTeacherMap);

        return courseDTOS;
    }

    @Override
    public List<CourseDTO> queryCourses(Long userId, Long courseId) {
        return courseMapperExt.queryCoursesAndCourseTeacher(userId, courseId);
    }

    @Override
    public List<CourseIndexInfoDTO> getIndexData() {

        // 没有登录，获取已共享的课程信息
        if (!userInfoHolder.isLogin()) {
            List<CourseDTO> courseDTOS = courseMapperExt.listSharedCourse(
                    Lists.newArrayList(
                            CourseStatusEnum.SHARED.getCode(),
                            CourseStatusEnum.SHARED_AND_NOT_VIEWED.getCode()
                    )
            );
            return convertCourse(courseDTOS);
        }

        List<CourseDTO> courseDTOS = Lists.newArrayList();

        // 已经登录，获取相应数据
        if (userInfoHolder.isStudent()) {
            // 获取学生关联关系的课程
            courseDTOS = listRelationCourseForStudent(userInfoHolder.getStudentClassIds());
        }
        if (userInfoHolder.isTeacher()) {
            // 获取自己创作的课程 或 关联的课程
            courseDTOS = queryTeacherCourse(userInfoHolder.getUserId());
        }

        // 获取已共享的课程
        List<CourseDTO> sharedCourses = courseMapperExt.listSharedCourse(
                Lists.newArrayList(CourseStatusEnum.SHARED.getCode()));

        return convertCourseIndex(courseDTOS, sharedCourses);

    }

    @Override
    public List<CourseDTO> queryTeacherCourse(Long userId) {
        // 获取自己创作的课程 或 关联的课程
        List<CourseDTO> courseDTOS = queryCourses(userId, null);
        if (CollectionUtils.isEmpty(courseDTOS)) return courseDTOS;

        // 获取课程的基本信息
        CourseBasicExample example = new CourseBasicExample();
        example.createCriteria()
                .andDeletedEqualTo(false)
                .andStatusIn(Lists.newArrayList(CourseStatusEnum.SAVE.getCode(), CourseStatusEnum.SHARED.getCode()))
                .andIdIn(courseDTOS.stream().map(CourseDTO::getCourseBasicId).distinct().collect(Collectors.toList()));
        List<CourseBasic> courseBasics = courseBasicMapper.selectByExample(example);

        // 将课程基本信息转换为Map结果集
        List<CourseDTO> data = Lists.newArrayList();
        Map<Long, CourseBasic> idMap = BeanUtil.mapByKey("id", courseBasics);
        if (MapUtils.isEmpty(idMap)) return data;

        // 转换
        courseDTOS.forEach(courseDTO -> {
            if (idMap.keySet().contains(courseDTO.getCourseBasicId())) {
                CourseBasic courseBasic = idMap.get(courseDTO.getCourseBasicId());
                courseDTO.setName(courseBasic.getName());
                courseDTO.setType(courseBasic.getType());
                courseDTO.setIcon(courseBasic.getIcon());
                courseDTO.setStatus(courseBasic.getStatus());
                courseDTO.setResourceId(courseBasic.getResourceId());
                courseDTO.setPreseted(courseBasic.getPreseted());
                List<Long> userIds = Lists.newArrayList(courseDTO.getUserId(), userId);
                userIds.addAll(courseDTO.getUserIds());
                courseDTO.setUserIds(userIds.stream().distinct().collect(Collectors.toList()));
                data.add(courseDTO);
            }
        });

        return data;
    }

    private void convert(List<CourseDTO> courseDTOS, Map<Long, List<CourseTeacher>> courseTeacherMap) {
        courseDTOS.forEach(courseDTO -> {

            // 主讲人
            List<Long> userIds = Lists.newArrayList(courseDTO.getUserId());

            // 获取助教 并添加到list集合中
            if (MapUtils.isNotEmpty(courseTeacherMap)
                    && CollectionUtils.isNotEmpty(courseTeacherMap.get(courseDTO.getId()))) {
                List<CourseTeacher> courseTeachers = courseTeacherMap.get(courseDTO.getId());
                List<Long> assistant = courseTeachers.stream()
                        .map(CourseTeacher::getUserId).collect(Collectors.toList());
                userIds.addAll(assistant);
            }

            courseDTO.setUserIds(userIds.stream().distinct().collect(Collectors.toList()));
        });
    }

    private List<CourseDTO> convertCourseDTO(List<CourseDTO> data) {
        // 配置图标放置到结果集中
        data = configService.convertIcon(data, LocalResourcesEnum.SYSTEM_FILE);

        // 判断角色 是否应该有预置资源问题
        if (RoleEnum.UNIVERSITY_TEACHER == RoleEnum.getByCode(userInfoHolder.getUser().getRole())) {
            return data;
        }

        // 获取预置资源信息
        List<Long> resourceIds = data.stream()
                .filter(courseDTO -> courseDTO.getResourceId() != null)
                .map(CourseDTO::getResourceId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(resourceIds)) return data;

        // 设置预置资源
        List<Resource> resources = resourceService.queryResource(resourceIds);
        Map<Long, Resource> resourceIdMap = BeanUtil.mapByKey("id", resources);
        data.forEach(courseDTO -> {
            if (courseDTO.getResourceId() != null) {
                courseDTO.setFileName(resourceIdMap.get(courseDTO.getResourceId()).getFileName());
                courseDTO.setRemark(resourceIdMap.get(courseDTO.getResourceId()).getRemark());
            }
        });
        return data;
    }

    private CourseBasic convertCourseParam(CourseParam param) {
        CourseBasic courseBasic = BeanUtil.transform(CourseBasic.class, param);
        if (userInfoHolder.isAdmin()) {
            courseBasic.setPreseted(true);
            courseBasic.setStatus(CourseStatusEnum.SHARED.getCode());
        }
        return courseBasic;
    }

    private void convertCourse(Course course, Long courseBasicId) {
        course.setCourseBasicId(courseBasicId);
        course.setOwnCourse(true);
    }

    private void checkCreateCourseParam(CourseParam param, Long id) {

        if (param == null) throw new BadRequestException();

        // 检查课程名称
        checkCourseName(param.getName(), id);

        // 检查参数
        if (StringUtils.isNotBlank(param.getTypeName())) {
            CourseTypeEnum courseTypeEnum = CourseTypeEnum.getByMessage(param.getTypeName());
            if (courseTypeEnum == null) {
                throw new BadRequestException("类型参数异常");
            }
            param.setType(courseTypeEnum.getCode());
        }

        if (param.getIcon() != null) {
            List<SystemConfig> systemConfigs = configService.listConfig(
                    Lists.newArrayList(param.getIcon()), null);
            if (CollectionUtils.isEmpty(systemConfigs)) {
                throw new BadRequestException("课程图标有更新，请刷新页面");
            }
        }

        // 检查镜像加载类型是否正确
        ImageLoadTypeEnum imageLoadTypeEnum = ImageLoadTypeEnum.getByMessage(param.getImageLoadTypeStr());
        if (imageLoadTypeEnum == null) {
            throw new BadRequestException("镜像加载类型不存在");
        }

        param.setImageLoadType(imageLoadTypeEnum.getCode());

    }

    private CourseDTO checkParamAndGetCourse(CourseParam param, Long courseId) {

        // 获取课程信息
        CourseDTO courseInfo = getCourseInfo(courseId);

        // 教师可以拖拽管理员的或者其他教师的，所以 不需要验证 preseted 是否是true了
        if (!courseInfo.getOwnCourse() && courseInfo.getName().equals(param.getName())) {
            throw new GlobalException("课程名称已存在");
        }

        // 检查参数
        checkCreateCourseParam(param, courseId);

        return courseInfo;

    }

    private void checkCourseName(String name, Long id) {

        Long courseBasicId = null;
        if (id != null) {
            Course course = courseMapper.selectByPrimaryKey(id);
            if (course == null) throw new BadRequestException("课程不存在");
            courseBasicId = course.getCourseBasicId();
        }

        CourseBasicExample example = new CourseBasicExample();
        CourseBasicExample.Criteria criteria = example.createCriteria();
        criteria.andNameEqualTo(name);
        criteria.andDeletedEqualTo(false);
        criteria.andStatusNotEqualTo(CourseStatusEnum.SHARED_AND_NOT_VIEWED.getCode());
        if (courseBasicId != null) {
            criteria.andIdNotEqualTo(courseBasicId);
        }
        List<CourseBasic> courseBasics = courseBasicMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(courseBasics)) {
            throw new BadRequestException("课程名称已存在");
        }

    }

    private List<CourseIndexInfoDTO> convertCourseIndex(List<CourseDTO> courseDTOS, List<CourseDTO> sharedCourses) {

        // 转换教师的课程与班级的关联关系
        convertCourseClass(courseDTOS);

        // 转换预置课程与班级的关联关系
        if (CollectionUtils.isNotEmpty(sharedCourses)) {
            sharedCourses.forEach(courseDTO -> courseDTO.setOwnCourse(false));
        }

        // 两个课程进行融合
        courseDTOS.addAll(sharedCourses);

        // 去重并转换
        return convertCourses(courseDTOS);

    }

    private void convertCourseClass(List<CourseDTO> courseDTOS) {
        if (CollectionUtils.isEmpty(courseDTOS)) return;

        // 获取班级和课程的关联关系
        List<ClassCourseDTO> classCourseDTOS = classService.listClassCourse(
                courseDTOS.stream().map(CourseDTO::getId).collect(Collectors.toList()), null);
        Map<Long, List<ClassCourseDTO>> courseIdMap = BeanUtil.aggByKeyToList("courseId", classCourseDTOS);

        courseDTOS.forEach(courseDTO -> {
            if (CollectionUtils.isEmpty(courseIdMap.get(courseDTO.getId()))) {
                courseDTO.setOwnCourse(false);
            } else {
                courseDTO.setOwnCourse(true);
            }
        });

        // 排序
        courseDTOS.sort(Comparator.comparing(CourseDTO::getOwnCourse, Comparator.reverseOrder())
                .thenComparing(CourseDTO::getStudied)
                .thenComparing(CourseDTO::getId, Comparator.reverseOrder()));
    }

    private List<CourseBasicDTO> convert(List<CourseBasicDTO> courseBasicDTOS) {

        if (CollectionUtils.isEmpty(courseBasicDTOS)) return courseBasicDTOS;

        // 配置图标
        configService.convertIcon(courseBasicDTOS, LocalResourcesEnum.SYSTEM_FILE);
        // 设置类型名称、状态码值
        courseBasicDTOS.forEach(data -> {
            data.setTypeName(data.getType() == null ? null : CourseTypeEnum.getMessageByCode(data.getType()));
            if (CourseStatusEnum.getByCode(data.getStatus()) == CourseStatusEnum.SHARED
                    && !data.getOwnCourse()) {
                data.setStatus(CourseStatusEnum.SAVE.getCode());
            }
        });

        return courseBasicDTOS;
    }

    private Map<Long, UserInfoDTO> getUserInfo(List<Long> userIds) {
        List<UserInfoDTO> users = userService.queryUserInfos(userIds, null);
        return BeanUtil.mapByKey("id", users);
    }

    private CourseIndexDTO convertCourseIndex(List<CourseIndexInfoDTO> data, Map<Long, UserInfoDTO> userInfoMap,
                                              Integer coursePageSize, CourseIndexDTO courseIndexDTO) {

        Boolean loginFlag = userInfoHolder.isLogin();

        Map<Integer, List<CourseIndexInfoDTO>> courseTypeMap = data.stream()
                .collect(Collectors.groupingBy(
                        CourseIndexInfoDTO::getType, LinkedHashMap::new, Collectors.toCollection(ArrayList::new)));

        courseTypeMap.forEach((type, courseDTOS) -> {

            // 配置教师姓名、状态、是否是自己的课程
            courseDTOS = setCourseData(courseDTOS, loginFlag, userInfoMap);

            CourseTypeEnum courseTypeEnum = CourseTypeEnum.getByCode(type);
            if (CourseTypeEnum.CORE == courseTypeEnum) {
                courseIndexDTO.setCoreCourses(BeanUtil.convertList(courseDTOS, coursePageSize));
            }
            if (CourseTypeEnum.EXPAND == courseTypeEnum) {
                courseIndexDTO.setExpandCourses(BeanUtil.convertList(courseDTOS, coursePageSize));
            }
        });
        return courseIndexDTO;
    }

    private List<CourseIndexInfoDTO> setCourseData(
            List<CourseIndexInfoDTO> courseDTOS, Boolean loginFlag, Map<Long, UserInfoDTO> userInfoMap) {
        // 配置教师姓名、状态、是否是自己的课程
        return courseDTOS.stream().map(courseDTO -> {
            CourseStatusEnum statusEnum = CourseStatusEnum.getByCode(courseDTO.getStatus());
            if (!loginFlag && statusEnum != null && statusEnum == CourseStatusEnum.SHARED_AND_NOT_VIEWED) {
                courseDTO.setStatusValue(statusEnum.getMessage());
            }
            if (userInfoMap != null && CollectionUtils.isNotEmpty(courseDTO.getUserIds())) {

                if (userInfoHolder.getUser() != null) {
                    int count = 0;
                    Long userId1 = userInfoHolder.getUserId();
                    for (Long userId : courseDTO.getUserIds()) {
                        if (userInfoMap.get(userId).getId().toString().equals(userInfoHolder.getUserId().toString())) {
                            count++;
                        }
                    }
                    if (count > 0) {
                        courseDTO.setUserNames(
                                courseDTO.getUserIds().stream()
                                        .map(userId -> userInfoMap.get(userId).getId().toString()
                                                .equals(userInfoHolder.getUserId().toString()) ?
                                                userInfoMap.get(userId).getName() :
                                                userInfoMap.get(userInfoHolder.getUserId()).getName() + "(助教)")
                                        .collect(Collectors.toList())
                        );
                    } else {
                        courseDTO.setUserNames(
                                courseDTO.getUserIds().stream()
                                        .map(userId -> (userInfoMap.get(userId).getName()))
                                        .collect(Collectors.toList()));
                    }
                } else {
                    courseDTO.setUserNames(
                            courseDTO.getUserIds().stream()
                                    .map(userId -> userInfoMap.get(userId) == null ?
                                            "" : userInfoMap.get(userId).getName())
                                    .collect(Collectors.toList()));
                }
            }
            if (courseDTO.getOwnCourse() && !Objects.equals(courseDTO.getUserId(), userInfoHolder.getUserId())) {
                courseDTO.setCreated(false);
            }
            return courseDTO;
        }).collect(Collectors.toList());
    }

    private List<Long> getOccupyCourseId(List<CourseDTO> courseInfo) {

        List<Long> courseIds = courseInfo.stream().map(CourseDTO::getId).distinct().collect(Collectors.toList());
        List<Long> courseBasicIds = courseInfo.stream().map(CourseDTO::getCourseBasicId).collect(Collectors.toList());

        // 先得查一下 这门课 是不是自己的课程，如果是自己的课程，可以删除其他教师的。 如果不是自己的课程，只能删除自己的。
        List<Long> ownCourseIds = courseInfo.stream()
                .filter(courseDTO -> courseDTO.getOwnCourse())
                .map(CourseDTO::getId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(ownCourseIds)) {
            return null;
        }

        CourseExample example = new CourseExample();
        example.createCriteria()
                .andCourseBasicIdIn(courseBasicIds)
                .andIdNotIn(courseIds)
                .andOwnCourseEqualTo(false)
                .andDeletedEqualTo(false);
        List<Course> courses = courseMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(courses)) return null;

        return courses.stream().map(Course::getId).distinct().collect(Collectors.toList());
    }

    private CourseDTO checkAndGetCourse(Long courseId) {
        CourseDTO courseInfo = getCourseInfo(courseId);
        if (!courseInfo.getOwnCourse()) {
            throw new GlobalException("当前课程不是本人制作，无法修改课程状态");
        }
        return courseInfo;
    }

    private CourseDTO getCourseInfo(Long courseId) {
        List<CourseDTO> courseDTOS = getCourseInfo(Lists.newArrayList(courseId));
        return courseDTOS.get(0);
    }

    private List<String> deleteCourseAndCourseBasic(
            List<Long> courseIds, Boolean logicDeleted, Boolean deleteResource) {

        // 删除course_extend表
        directionService.deleteCourseExtend(null, courseIds);

        // 修改course表
        CourseExample example = new CourseExample();
        example.createCriteria().andIdIn(courseIds);
        List<Course> courses = courseMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(courses)) return null;

        if (logicDeleted) {
            Course course = new Course();
            course.setDeleted(true);
            courseMapper.updateByExampleSelective(course, example);
        } else {
            courseMapper.deleteByExample(example);
        }

        example.clear();
        example.createCriteria()
                .andCourseBasicIdIn(courses.stream().map(Course::getCourseBasicId).collect(Collectors.toList()))
                .andIdNotIn(courseIds)
                .andDeletedEqualTo(false);
        List<Course> dbExistCourses = courseMapper.selectByExample(example);

        List<Long> basicIds = courses.stream().map(Course::getCourseBasicId).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(dbExistCourses)) {
            List<Long> dbExistCoursesBasics = dbExistCourses.stream()
                    .map(Course::getCourseBasicId).collect(Collectors.toList());
            basicIds.removeAll(dbExistCoursesBasics);
        }

        if (CollectionUtils.isEmpty(basicIds)) return null;

        // 修改course_basic表 如果被人占用，就不删除course_basic
        CourseBasicExample basicExample = new CourseBasicExample();
        basicExample.createCriteria().andIdIn(basicIds);
        List<CourseBasic> courseBasics = courseBasicMapper.selectByExample(basicExample);
        if (CollectionUtils.isEmpty(courseBasics)) return null;

        if (logicDeleted) {
            CourseBasic courseBasic = new CourseBasic();
            courseBasic.setDeleted(true);
            courseBasicMapper.updateByExampleSelective(courseBasic, basicExample);
        } else {
            courseBasicMapper.deleteByExample(basicExample);
        }

        // 查询资源信息
        List<Long> resourceIds = courseBasics.stream()
                .filter(courseBasic -> courseBasic.getResourceId() != null)
                .map(CourseBasic::getResourceId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(resourceIds)) return null;
        List<Resource> resources = resourceService.queryResource(resourceIds);
        if (CollectionUtils.isEmpty(resources)) return null;

        // 删除预置资源
        resourceService.deleteBatch(resourceIds);

        // 获取需要删除预置资源路径
        List<String> result = Lists.newArrayList();
        resources.forEach(resource -> {
            result.add(LocalResourcesEnum.COURSE.getLocalUploadPath(
                    new String[]{String.valueOf(resource.getRemark())}, resource.getFileName()));
        });

        // 是否删除静态资源资源
        if (deleteResource) {
            result.forEach(s -> FileUtil.del(s));
        }
        return result;
    }

    private CourseBasic getCourseBasic(Long courseBasicId) {
        return courseBasicMapper.selectByPrimaryKey(courseBasicId);
    }

    private CourseIndexDataDTO convert(
            boolean loginFlag, Map<Long, UserInfoDTO> userInfoMap,
            Integer coursePageSize, List<CourseIndexInfoDTO> data) {

        // 配置教师姓名、状态、是否是自己的课程
        data = setCourseData(data, loginFlag, userInfoMap);

        List<CourseIndexInfoDTO> coreCourses = data.stream()
                .filter(indexData -> Objects.equals(indexData.getType(), CourseTypeEnum.CORE.getCode()))
                .collect(Collectors.toList());
        List<CourseIndexInfoDTO> expandCourses = data.stream()
                .filter(indexData -> Objects.equals(indexData.getType(), CourseTypeEnum.EXPAND.getCode()))
                .collect(Collectors.toList());

        // 设置所有课程、核心课程、拓展课程
        CourseIndexDataDTO result = new CourseIndexDataDTO();
        result.setCourses(BeanUtil.convertList(data, coursePageSize));
        result.setCoreCourses(BeanUtil.convertList(coreCourses, coursePageSize));
        result.setExpandCourses(BeanUtil.convertList(expandCourses, coursePageSize));
        return result;
    }

    private void convertTechnologyDTO(Integer technologyPageSize, CourseIndexDTO courseIndexDTO) {
        List<TechnologyDTO> technologyDTOS = technologyService.queryTechnologyFrequency();
        technologyDTOS = technologyDTOS.stream()
                .filter(technologyDTO -> technologyDTO.getUseNum() > 0).collect(Collectors.toList());
        courseIndexDTO.setTechnologies(BeanUtil.convertList(technologyDTOS, technologyPageSize));
    }

    private void convertBusinessDTO(Integer casePageSize, CourseIndexDTO courseIndexDTO) {
        List<BusinessDTO> businessDTOS = businessCaseService.listBusiness();
        courseIndexDTO.setBusinessCase(BeanUtil.convertList(businessDTOS, casePageSize));
    }

    private void convertCourseIndexDTO(
            Integer coursePageSize, List<CourseIndexInfoDTO> data, CourseIndexDTO indexDTO) {

        indexDTO.setRequestCourse(CollectionUtils.isEmpty(indexDTO.getDirections()) ? false : true);

        if (indexDTO.getRequestCourse()) return;

        // 配置图标放置到结果集中
        data = configService.convertIcon(data, LocalResourcesEnum.SYSTEM_FILE);

        // 获取教师信息
        Map<Long, UserInfoDTO> userInfoMap = getUserMap(data);

        // 转换
        convertCourseIndex(data, userInfoMap, coursePageSize, indexDTO);

    }

    private List<Direction> queryDirection(List<Integer> types, List<Long> courseIds, List<Long> ownCourseIds) {

        // 获取专业方向
        List<Direction> directions = directionService.queryDirection(types, null);
        if (CollectionUtils.isEmpty(directions)) return null;

        // 获取课程与专业方向的绑定关系 并将 专业方向按照课程进行过滤
        List<CourseExtend> courseExtends = directionService.queryCourseExtend(
                directions.stream().map(Direction::getId).collect(Collectors.toList()), courseIds);
        List<Long> directionIds = courseExtends.stream().map(CourseExtend::getDirectionId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(directionIds)) return directions;

        // 当用户登陆的时候，对学校类型进行过滤
        if (userInfoHolder.isLogin()) {
            List<Permission> permissions = userService.queryUserPermission(userInfoHolder.getUserId());
            if (CollectionUtils.isNotEmpty(permissions)) {
                List<Integer> status = permissions.stream().map(Permission::getStatus).collect(Collectors.toList());
                List<Direction> data = directions.stream()
                        .filter(direction -> status.contains(direction.getType())
                                && directionIds.contains(direction.getId())).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(ownCourseIds)) return data;

                List<Long> partIds = data.stream().map(Direction::getId).collect(Collectors.toList());
                List<Long> otherIds = directions.stream()
                        .filter(direction -> !partIds.contains(direction.getId()))
                        .map(Direction::getId).collect(Collectors.toList());

                List<Long> directionIdList = courseExtends.stream()
                        .filter(courseExtend -> ownCourseIds.contains(courseExtend.getCourseId())
                                && otherIds.contains(courseExtend.getDirectionId()))
                        .map(CourseExtend::getDirectionId).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(directionIdList)) return data;

                List<Direction> addData = directions.stream()
                        .filter(direction -> directionIdList.contains(direction.getId())).collect(Collectors.toList());

                addData.addAll(data);

                // 排序
                addData.sort(Comparator.comparing(Direction::getType).thenComparing(Direction::getOrderNum));

                return addData;

            }
        }

        return directions.stream()
                .filter(direction -> directionIds.contains(direction.getId())).collect(Collectors.toList());

    }

    private void convertDirectionData(
            List<Long> courseIds, List<Long> ownCourseIds, CourseIndexDTO indexDTO, List<ValueDTO> configs) {

        // 获取专业方向
        List<Direction> directions = queryDirection(
                configs.stream().map(ValueDTO::getId).collect(Collectors.toList()), courseIds, ownCourseIds);
        if (CollectionUtils.isEmpty(directions)) return;

        // 转换
        Map<Long, ValueDTO> configMap = BeanUtil.mapByKey("id", configs);
        List<DirectionDataDTO> directionData = Lists.newArrayList();
        directions.forEach(direction -> {
            ValueDTO valueDTO = configMap.get(direction.getType());
            DirectionDataDTO directionDataDTO = new DirectionDataDTO();
            directionDataDTO.setId(direction.getId());
            directionDataDTO.setName(direction.getName());
            directionDataDTO.setKeyValue(valueDTO.getKeyValue());
            directionData.add(directionDataDTO);
        });

        indexDTO.setDirections(directionData);

    }

    private void convertStatistics(List<CourseIndexInfoDTO> data, CourseIndexDTO courseIndexDTO) {

        if (!userInfoHolder.isLogin()) {
            return;
        }
        if (userInfoHolder.isStudent()) {
            // 获取正在学习的课程
            courseIndexDTO.setStudiedCourseNum(
                    CollectionUtils.isEmpty(data) ? 0 : data.stream()
                            .filter(courseDTO -> courseDTO.getOwnCourse() && !courseDTO.getStudied())
                            .collect(Collectors.toList()).size());
            // 获取实验时长
            courseIndexDTO.setExperimentTime(
                    experimentStatisticService.getExperimentDuration(userInfoHolder.getUserId()));

            // 获取已经提交作业数量
            courseIndexDTO.setSubmittedExercisesNum(practiceService.getCount(userInfoHolder.getUserId()));

            // 获取已提交报告数量
            courseIndexDTO.setSubmittedReportNum(
                    experimentService.getCount(userInfoHolder.getUserId(), ReportTypeEnum.EXPERIMENT));
        }
        if (userInfoHolder.isTeacher()) {

            // 获取班级和课程的关联关系
            Map<Long, List<ClassCourseDTO>> courseClassMap = queryCourseClassMap(
                    data.stream()
                            .filter(courseIndexInfoDTO -> courseIndexInfoDTO.getOwnCourse())
                            .collect(Collectors.toList()),
                    userInfoHolder.getUserId());
            if (MapUtils.isEmpty(courseClassMap)) return;

            // 获取上课的班级
            Set<Long> resultClassIds = Sets.newHashSet();
            courseClassMap.values().forEach(classCourseDTOS -> resultClassIds.addAll(
                    classCourseDTOS.stream().map(ClassCourseDTO::getId).collect(Collectors.toList())));
            courseIndexDTO.setClasses(
                    new StatisticsDTO(resultClassIds.stream().count(), null, null));

            // 获取当前教师的待审批随堂练习 注意：一定要考虑自然班级的情况
            courseIndexDTO.setUnreviewedPractice(checkService.getClassCheckCount(courseClassMap, CheckEnum.PRACTICE));

            // 获取当前教师的待审批实验报告 注意：一定要考虑自然班级的情况
            courseIndexDTO.setUnreviewedReport(checkService.getClassCheckCount(courseClassMap, CheckEnum.EXPERIMENT));

            // 获取当前教师的待审批试卷
            courseIndexDTO.setUnreviewedTestPaper(paperAnswerSheetService.getClassCheckCount(courseClassMap));

        }
    }

    @Override
    public List<CourseTeacher> queryCourseTeacher(List<Long> courseIds, Long userId, Long classId) {
        CourseTeacherExample example = new CourseTeacherExample();
        CourseTeacherExample.Criteria criteria = example.createCriteria();
        if (CollectionUtils.isNotEmpty(courseIds)) {
            criteria.andCourseIdIn(courseIds);
        }
        if (userId != null) {
            criteria.andUserIdEqualTo(userId);
        }
        if (classId != null) {
            criteria.andClassIdEqualTo(classId);
        }
        return courseTeacherMapper.selectByExample(example);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCourseTeachers(Long courseId, List<Long> classIds) {
        CourseTeacherExample example = new CourseTeacherExample();
        CourseTeacherExample.Criteria criteria = example.createCriteria();
        if (courseId != null) {
            criteria.andCourseIdEqualTo(courseId);
        }
        if (CollectionUtils.isNotEmpty(classIds)) {
            criteria.andClassIdIn(classIds);
        }
        courseTeacherMapper.deleteByExample(example);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCourseTeachers(List<Long> userIds) {
        CourseTeacherExample example = new CourseTeacherExample();
        example.createCriteria().andUserIdIn(userIds);
        courseTeacherMapper.deleteByExample(example);
    }

    @Override
    public Boolean queryCourseTeachers(Long courseId, Long userId) {
        List<Long> userIdsall = courseTeacherMapper.queryuserIdsOther(courseId);
        List<Long> userIds = courseTeacherMapper.queryuserIds(courseId);
        if (CollectionUtils.isNotEmpty(userIds)) {
            userIdsall.addAll(userIds);
        }
        for (Long userid : userIdsall) {
            if (userId.equals(userid)) throw new GlobalException("已经存在此教师");
        }
        return true;
    }

    @Override
    public List<CourseSort> queryCourseSort(List<Long> courseIds) {
        if (CollectionUtils.isEmpty(courseIds)) return null;
        CourseSortExample courseSortExample = new CourseSortExample();
        courseSortExample.createCriteria().andCourseIdIn(courseIds);
        courseSortExample.setOrderByClause("order_num asc");
        return courseSortMapper.selectByExample(courseSortExample);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOrUpdateCourseSort(Long courseId, List<CreateOrUpdateCourseSortParam> params) {

        // 检查
        checkCourseSort(courseId, params);

        // 转换
        List<CourseSort> courseSorts = convertCourseSort(courseId, params);

        // 数据库中的数据
        List<CourseSort> dbCourseData = queryCourseSort(Lists.newArrayList(courseId));

        // 插入或修改数据库
        insertOrUpdateCourseSort(dbCourseData, courseSorts);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCourseSort(List<Long> courseSortIds, List<Long> courseIds) {
        if (CollectionUtils.isEmpty(courseSortIds) && CollectionUtils.isEmpty(courseIds)) return;
        CourseSortExample example = new CourseSortExample();
        CourseSortExample.Criteria criteria = example.createCriteria();
        if (CollectionUtils.isNotEmpty(courseSortIds)) {
            criteria.andIdIn(courseSortIds);
        }
        if (CollectionUtils.isNotEmpty(courseIds)) {
            criteria.andCourseIdIn(courseIds);
        }
        courseSortMapper.deleteByExample(example);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertBatchCourseSort(List<CourseSort> data) {
        courseSortMapperExt.insertBatch(data);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOrUpdateResource(Long id, ResourcesTypeEnum resourcesTypeEnum, CreateResourceParam param) {

        ResourceRelationTypeEnum typeEnum = ResourceRelationTypeEnum.COURSE;

        // 删除课程资源
        List<String> deleteResourcePath = deleteCourseResource(
                Lists.newArrayList(id), Lists.newArrayList(resourcesTypeEnum), typeEnum, false);

        // 插入资源
        String filePath = LocalResourcesEnum.COURSE.getLocalUploadPath(
                new String[]{String.valueOf(id)}, "");
        String fileName = RandomUtil.simpleUUID();
        List<String> fileNameList = Lists.newArrayList(fileName + ".md", fileName + ".html");

        List<Resource> resource = convertResource(param.getName(), String.valueOf(id), fileNameList, resourcesTypeEnum);
        resourceService.insertBatch(resource);
        List<ResourceRelation> resourceRelations = convertResourceRelation(
                resource.stream().map(Resource::getId).collect(Collectors.toList()), id, typeEnum);
        resourceService.insertBatchResourceRelation(resourceRelations);

        // 下载md文件和html文件
        fileNameList.forEach(s -> {
            if (s.contains(FileTypeEnum.MARKDOWN.getExtension())) {
                mdHtmlFileService.writeFile(param.getContent(), filePath, s);
            }
            if (s.contains(FileTypeEnum.HTML.getExtension())) {
                mdHtmlFileService.writeFile(param.getHtmlContent(), filePath, s);
            }
        });

        // 删除资源
        if (CollectionUtils.isNotEmpty(deleteResourcePath)) {
            deleteResourcePath.forEach(s -> FileUtil.del(s));
        }

    }

    @Override
    public Map<String, ResourceInfoDTO> queryResource(Long id, List<ResourcesTypeEnum> typeEnums) {

        // 将参数的枚举值转换为正确数据类型
        List<Integer> types = typeEnums.stream()
                .map(resourcesTypeEnum -> resourcesTypeEnum.getCode()).collect(Collectors.toList());

        // 根据课程id和类型 从resource_relation和resource表进行查询，获取到课程资源数据 并转换成Map
        List<ResourceRelationDTO> resourceData = resourceService.getResourceRelationInfo(
                Lists.newArrayList(id), types, null, ResourceRelationTypeEnum.COURSE.getCode());
        Map<ResourcesTypeEnum, List<ResourceRelationDTO>> typeMap = resourceData.stream()
                .collect(Collectors.groupingBy(o -> ResourcesTypeEnum.getByCode(o.getType())));

        // 转换
        Map<String, ResourceInfoDTO> map = Maps.newHashMap();
        for (ResourcesTypeEnum typeEnum : typeEnums) {
            String key = Arrays.stream(StringUtils.split(typeEnum.name(), "_"))
                    .map(str -> StringUtils.join(str.substring(0, 1), str.substring(1).toLowerCase()))
                    .reduce((str1, str2) -> StringUtils.join(str1, str2))
                    .map(s -> StringUtils.join(s.substring(0, 1).toLowerCase(), s.substring(1))).get();
            map.put(key, convertResourceDTOS(typeEnum, typeMap));
        }
        return map;
    }

    @Override
    public List<ResourceDTO> readContent(List<ResourceDTO> resourceDTOS, ResourcesTypeEnum typeEnum) {
        return resourceDTOS.stream()
                .map(resourceDTO -> {

                    // 设置文件路径
                    resourceDTO.setFilePath(LocalResourcesEnum.CHAPTER.getMappingUrl(
                            new String[]{resourceDTO.getRemark()}, resourceDTO.getFileName()));

                    // 设置markdown内容
                    if (typeEnum == ResourcesTypeEnum.COURSE_OUTLINE
                            && StringUtils.isNotBlank(resourceDTO.getFileName())
                            && Objects.equals(FileTypeEnum.MARKDOWN.getExtension(),
                            StringUtils.join(".",
                                    StrUtil.subAfter(resourceDTO.getFileName(), ".", true)))) {

                        resourceDTO.setFilePath("");

                        try {
                            resourceDTO.setContent(
                                    mdHtmlFileService.readFile(
                                            LocalResourcesEnum.COURSE.getLocalUploadPath(
                                                    new String[]{resourceDTO.getRemark()}, ""),
                                            resourceDTO.getFileName()
                                    )
                            );
                        } catch (Exception e) {
                            resourceDTO.setContent("");
                        }

                    }

                    // 设置html内容
                    if (typeEnum == ResourcesTypeEnum.COURSE_OUTLINE
                            && StringUtils.isNotBlank(resourceDTO.getFileName())
                            && Objects.equals(FileTypeEnum.HTML.getExtension(),
                            StringUtils.join(".",
                                    StrUtil.subAfter(resourceDTO.getFileName(), ".", true)))) {

                        resourceDTO.setFilePath("");

                        try {
                            resourceDTO.setHtmlContent(
                                    mdHtmlFileService.readFile(
                                            LocalResourcesEnum.COURSE.getLocalUploadPath(
                                                    new String[]{resourceDTO.getRemark()}, ""),
                                            resourceDTO.getFileName()
                                    )
                            );
                        } catch (Exception e) {
                        }
                    }

                    return resourceDTO;
                }).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> deleteCourseResource(
            List<Long> ids, List<ResourcesTypeEnum> resourcesTypeEnum,
            ResourceRelationTypeEnum typeEnum, boolean deleteResource) {

        // 获取资源
        List<ResourceRelationDTO> resourceRelationInfo = resourceService.getResourceRelationInfo(
                ids, resourcesTypeEnum.stream().map(ResourcesTypeEnum::getCode).collect(Collectors.toList()),
                null, typeEnum.getCode());

        // 过滤资源是否被其他老师占用。若占用则不删除资源
        List<ResourceRelationDTO> filterData = filterOccupyResource(
                resourceRelationInfo.stream().map(ResourceRelationDTO::getResourceId).collect(Collectors.toList()),
                resourceRelationInfo.stream()
                        .map(ResourceRelationDTO::getResourceRelationId).collect(Collectors.toList()),
                resourceRelationInfo
        );

        // 删除资源数据库
        if (CollectionUtils.isNotEmpty(filterData)) {
            resourceService.deleteBatch(
                    filterData.stream().map(ResourceRelationDTO::getResourceId).collect(Collectors.toList()));
        }
        if (CollectionUtils.isNotEmpty(resourceRelationInfo)) {
            resourceService.deleteResourceRelation(
                    resourceRelationInfo.stream().map(ResourceRelationDTO::getResourceRelationId)
                            .collect(Collectors.toList())
            );
        }

        // 获取删除资源的路径
        List<String> result = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(filterData)) {
            filterData.forEach(data ->
                    result.add(LocalResourcesEnum.COURSE.getLocalUploadPath(
                            new String[]{String.valueOf(data.getRemark())}, data.getFileName())));
        }

        // 是否删除静态资源资源
        if (deleteResource && CollectionUtils.isNotEmpty(result)) {
            result.forEach(s -> FileUtil.del(s));
        }

        return result;

    }

    private ResourceInfoDTO convertResourceDTOS(
            ResourcesTypeEnum typeEnum, Map<ResourcesTypeEnum, List<ResourceRelationDTO>> typeMap) {

        List<ResourceRelationDTO> data = typeMap.get(typeEnum);

        // 将数据转换并按照资源id从小到大排序
        List<ResourceDTO> resourceDTOS = BeanUtil.batchTransform(ResourceDTO.class, data);
        resourceDTOS = readContent(resourceDTOS, typeEnum);

        // 将资源转换为创作课程结果集 和 展示版本的资源信息
        return typeEnum.getResourceInfoDTO(resourceDTOS);

    }

    private List<ResourceRelationDTO> filterOccupyResource(
            List<Long> resourceIds, List<Long> resourceRelationIds, List<ResourceRelationDTO> data) {

        if (CollectionUtils.isEmpty(data)) return data;

        ResourceRelationExample example = new ResourceRelationExample();
        example.createCriteria()
                .andTypeEqualTo(ResourceRelationTypeEnum.COURSE.getCode()).andIdNotIn(resourceRelationIds)
                .andResourceIdIn(resourceIds);
        List<ResourceRelation> resourceRelations = resourceService.queryResourceRelation(example);
        if (CollectionUtils.isEmpty(resourceRelations)) return data;

        List<Long> existResourceIds = resourceRelations.stream()
                .map(ResourceRelation::getResourceId).collect(Collectors.toList());

        return data.stream()
                .filter(resourceRelationDTO -> !existResourceIds.contains(resourceRelationDTO.getResourceId()))
                .collect(Collectors.toList());

    }

    private List<Resource> convertResource(
            String name, String remark, List<String> fileNameList, ResourcesTypeEnum resourcesTypeEnum) {
        List<Resource> resources = Lists.newArrayList();
        fileNameList.forEach(s -> {
            Resource resource = new Resource();
            resource.setRemark(remark);
            resource.setFileName(s);
            resource.setName(name);
            resource.setType(resourcesTypeEnum.getCode());
            resources.add(resource);
        });
        return resources;
    }

    private List<ResourceRelation> convertResourceRelation(
            List<Long> resourceIds, Long id, ResourceRelationTypeEnum typeEnum) {
        List<ResourceRelation> resourceRelations = Lists.newArrayList();
        resourceIds.forEach(resourceId -> {
            ResourceRelation resourceRelation = new ResourceRelation();
            resourceRelation.setType(typeEnum.getCode());
            resourceRelation.setObjId(id);
            resourceRelation.setResourceId(resourceId);
            resourceRelations.add(resourceRelation);
        });
        return resourceRelations;
    }

    private List<CourseSort> queryCourseSortByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) return null;
        CourseSortExample courseSortExample = new CourseSortExample();
        courseSortExample.createCriteria().andIdIn(ids);
        courseSortExample.setOrderByClause("order_num asc");
        return courseSortMapper.selectByExample(courseSortExample);
    }

    private void checkCourseSort(Long courseId, List<CreateOrUpdateCourseSortParam> params) {

        // 检查名称是否重复
        List<String> names = params.stream().map(CreateOrUpdateCourseSortParam::getName).collect(Collectors.toList());
        HashSet<String> setData = Sets.newHashSet(names);
        if (!Objects.equals(setData.size(), names.size())) {
            throw new BadRequestException("课程分类名称不能重复");
        }

        // 检查id是否正确
        List<Long> ids = params.stream()
                .filter(createCourseSortParam -> createCourseSortParam.getId() > 0)
                .map(CreateOrUpdateCourseSortParam::getId).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(ids)) return;

        List<CourseSort> dbCourseSorts = queryCourseSortByIds(ids);
        Long errorCount = dbCourseSorts.stream()
                .map(CourseSort::getCourseId).distinct()
                .filter(dbCourseId -> dbCourseId == null || !Objects.equals(dbCourseId, courseId)).count();
        if (!Objects.equals(dbCourseSorts.size(), ids.size()) || errorCount > 0) {
            throw new BadRequestException();
        }

    }

    private void insertOrUpdateCourseSort(List<CourseSort> dbCourseData, List<CourseSort> insertOrUpdateData) {

        insertOrUpdateData = insertOrUpdateData == null ? Lists.newArrayList() : insertOrUpdateData;

        List<Long> dbIds = dbCourseData.stream().map(CourseSort::getId).collect(Collectors.toList());

        // 添加
        List<CourseSort> insertData = insertOrUpdateData.stream()
                .filter(courseSort -> courseSort.getId() == 0).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(insertData)) {
            insertBatchCourseSort(insertData);
        }

        // 修改
        List<CourseSort> updateData = insertOrUpdateData.stream()
                .filter(courseSort -> courseSort.getId() > 0).collect(Collectors.toList());
        List<Long> updateIds = updateData.stream().map(CourseSort::getId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(updateData)) {
            courseSortMapperExt.updateBatch(updateData);
        }

        // 删除
        List<Long> deleteIds = dbIds.stream()
                .filter(courseSortId -> !updateIds.contains(courseSortId)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(deleteIds)) {
            chapterService.deleteChapterCourseSort(deleteIds, null);
            deleteCourseSort(deleteIds, null);
        }
    }

    private List<CourseSort> convertCourseSort(Long courseId, List<CreateOrUpdateCourseSortParam> params) {
        if (CollectionUtils.isEmpty(params)) return null;
        List<CourseSort> courseSorts = BeanUtil.batchTransform(CourseSort.class, params);
        for (int i = 0; i < courseSorts.size(); i++) {
            CourseSort courseSort = courseSorts.get(i);
            courseSort.setOrderNum(i + 1);
            courseSort.setCourseId(courseId);
        }
        return courseSorts;
    }

    private Map<Long, UserInfoDTO> getUserMap(List<CourseIndexInfoDTO> data) {
        if (data.stream()
                .filter(courseIndexInfoDTO -> CollectionUtils.isNotEmpty(courseIndexInfoDTO.getUserIds()))
                .count() == 0) {
            return null;
        }
        List<Long> userIds = Arrays.stream(data.stream()
                .filter(courseIndexInfoDTO -> CollectionUtils.isNotEmpty(courseIndexInfoDTO.getUserIds()))
                .map(courseIndexInfoDTO -> StringUtils.join(courseIndexInfoDTO.getUserIds(), ","))
                .collect(Collectors.joining(",")).split(","))
                .map(Long::valueOf).distinct().collect(Collectors.toList());
        return getUserInfo(userIds);
    }

    private void convertSkillDTO(Integer skillPageSize, CourseIndexDTO indexDTO) {

        indexDTO.setSkills(BeanUtil.convertList(querySkill(null), skillPageSize));

    }

    private List<List<Long>> convertCourseDirection(Long courseId) {
        List<List<Long>> result = Lists.newArrayList();
        List<CourseExtend> courseExtends = directionService.queryCourseExtend(
                null, Lists.newArrayList(courseId));
        if (CollectionUtils.isNotEmpty(courseExtends)) {
            List<Direction> directionList = directionService.queryDirection(courseExtends.stream()
                    .map(CourseExtend::getDirectionId).collect(Collectors.toList()));
            if (CollectionUtils.isNotEmpty(directionList)) {
                directionList.forEach(direction -> {
                    result.add(
                            Lists.newArrayList(Long.valueOf(direction.getType()), direction.getId()));
                });
            }

        }
        return result;
    }


    @Transactional
    public String insertSkill(List<SkillDTO> list, Integer skillId, MultipartFile file, Integer role) {

        //level 1
        try {
            courseMapperExt.updateSkill(list.get(0).getPost(), skillId, null);
            //level 2
            if (role == 1) {
                SkillNotes skilllevel1 = courseMapperExt.querySkillById(skillId);
                deleteSkill(skilllevel1.getId());
            }
            SkillNotes skillDTOnew1 = new SkillNotes();
            skillDTOnew1.setLevel(2);
            skillDTOnew1.setParentId(skillId);
            skillDTOnew1.setName(list.get(0).getDescribe());
            skillDTOnew1.setCreateTime(new Date());
            courseMapperExt.insertSkill(skillDTOnew1);
            //level 3
            int count = 0;
            Map<String, Integer> map = new HashMap<String, Integer>();
            for (SkillDTO skillDTO : list) {
                count++;
                if (!"".equals(skillDTO.getSkillModule())) {
                    SkillNotes skillDTOnew2 = new SkillNotes();
                    skillDTOnew2.setLevel(3);
                    skillDTOnew2.setParentId(skillDTOnew1.getId());
                    skillDTOnew2.setName(skillDTO.getSkillModule());
                    skillDTOnew2.setCreateTime(new Date());
                    courseMapperExt.insertSkill(skillDTOnew2);
                    map.put(StringUtils.join(count), skillDTOnew2.getId());
                }
            }
            Map map4 = querySkillStutas(map, list.size() + 1);
            //level 4
            Map<String, Integer> map1 = new HashMap<String, Integer>();
            int count1 = 0;
            for (SkillDTO skillDTO : list) {
                count1++;
                if (!"".equals(skillDTO.getSubSkill())) {
                    SkillNotes skillDTOnew3 = new SkillNotes();
                    skillDTOnew3.setLevel(4);
                    skillDTOnew3.setParentId(queryParentId(map4, count1));
                    skillDTOnew3.setName(skillDTO.getSubSkill());
                    courseMapperExt.insertSkill(skillDTOnew3);
                    map1.put(StringUtils.join(count1), skillDTOnew3.getId());
                }
            }
            Map map5 = querySkillStutas(map1, list.size() + 1);
            //level 5
            int count2 = 0;
            Map<String, Integer> map2 = new HashMap<String, Integer>();
            for (SkillDTO skillDTO : list) {
                count2++;
                if (!"".equals(skillDTO.getKnowledgePoints())) {
                    SkillNotes skillDTOnew4 = new SkillNotes();
                    skillDTOnew4.setLevel(5);
                    skillDTOnew4.setParentId(queryParentId(map5, count2));
                    skillDTOnew4.setName(skillDTO.getKnowledgePoints());
                    courseMapperExt.insertSkill(skillDTOnew4);
                    map2.put(StringUtils.join(count2), skillDTOnew4.getId());
                }
            }
            Map map6 = querySkillStutas(map2, list.size() + 1);
            //level 6
            Long userId = userInfoHolder.getUserId();
            int count3 = 0;
            for (SkillDTO skillDTO : list) {
                count3++;
                if (!"".equals(skillDTO.getKnowledgePoints())) {
                    SkillNotes skillDTOnew5 = new SkillNotes();
                    skillDTOnew5.setLevel(6);
                    skillDTOnew5.setParentId(queryParentId(map6, count3));
                    List<Map<String, Object>> listmap = courseMapperExt.querySkillCourse(userId, skillDTO.getCourseName());
                    String id = "0";
                    String key_value = "";
                    if (listmap.size() > 1 && listmap != null) {
                        for (Map<String, Object> map3 : listmap) {
                            if (!"1".equals(map3.get("is_own_course"))) {
                                id = map3.get("id") == null ? "" : map3.get("id").toString();
                                key_value = map3.get("key_value") == null ? "" : map3.get("key_value").toString();
                            }
                        }

                    } else if (listmap != null && listmap.size() == 1) {
                        id = listmap.get(0).get("id") == null ? "" : listmap.get(0).get("id").toString();
                        key_value = listmap.get(0).get("key_value") == null ? "" : listmap.get(0).get("key_value").toString();
                    }
                    skillDTOnew5.setIconValue(key_value);
                    skillDTOnew5.setCourseId(Integer.valueOf(id));
                    skillDTOnew5.setName(skillDTO.getCourseName());
                    courseMapperExt.insertSkill(skillDTOnew5);

                }
            }
            courseMapperExt.updateSkill(null, skillId, 1);
            String pathName = ExcelsUtil.uploadExeSkill(file, skillId);
            List<ResourceRelationDTO> resourceRelationInfo = systemResourceService.getResourceRelationInfo(Lists.newArrayList(Long.valueOf(skillId)), Lists.newArrayList(16), null, 3);
            if (resourceRelationInfo != null && resourceRelationInfo.size() > 0) {
                systemResourceService.deleteResourceRelation(Lists.newArrayList(resourceRelationInfo.get(0).getResourceRelationId()));
                systemResourceService.deleteBatch(Lists.newArrayList(resourceRelationInfo.get(0).getResourceId()));
            }
            Resource resource = new Resource();
            resource.setFileName(pathName);
            resource.setName(ResourcesTypeEnum.SKILL_INFO.getMessage());
            resource.setType(ResourcesTypeEnum.SKILL_INFO.getCode());
            systemResourceService.insertResource(resource);
            ResourceRelation resourceRelation = new ResourceRelation();
            resourceRelation.setObjId(Long.valueOf(skillId));
            resourceRelation.setType(3);
            resourceRelation.setResourceId(resource.getId());
            systemResourceService.insertBatchResourceRelation(Lists.newArrayList(resourceRelation));
            return "";
        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw new BadRequestException("请检查上传的文件是否正确");
        }

    }

    public Map querySkillStutas(Map<String, Integer> map, Integer count) {
        Map<String, Integer> mapnew = map.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
        List list = Lists.newArrayList();
        for (String key : mapnew.keySet()) {
            list.add(key);
        }
        list.add(count);
        String countold = "";
        Map map1 = new HashMap();
        if (CollectionUtils.isNotEmpty(list)) {
            for (int i = 0; i < 1; i++) {
                for (int j = 1; j < list.size(); j++) {
                    if (j == 1) {
                        map1.put(list.get(i).toString() + "-" + list.get(j).toString(), mapnew.get(list.get(i).toString()));
                    } else {
                        if (Integer.valueOf(list.get(j).toString()) == count) {
                            map1.put(countold + "-" + list.get(j).toString(), mapnew.get(countold));
                        } else {
                            map1.put(countold + "-" + list.get(j).toString(), mapnew.get(countold));
                        }
                    }
                    countold = list.get(j).toString();
                }
            }
        }
        return map1;
    }

    private Integer queryParentId(Map<String, Integer> map, Integer count) {
        Integer value = null;
        for (String countnew : map.keySet()) {
            String[] split = countnew.split("-");
            if (Integer.valueOf(split[1]) == 1 && count == 1) {
                value = Integer.valueOf(map.get(countnew).toString());
            } else {
                for (int i = Integer.valueOf(split[0]); i < Integer.valueOf(split[1]); i++) {
                    if (count == i) {
                        value = Integer.valueOf(map.get(countnew).toString());
                    }
                }
            }
        }
        return value;
    }


    @Override
    public List<SkillNotes> querySkill(Integer id) {
        List<SkillNotes> childLists = null;
        childLists = courseMapperExt.getChildLists(id);
        if (id == null) {
            String mappingUrl = LocalResourcesEnum.SYSTEM_FILE.getMappingUrl();
            childLists = courseMapperExt.getChildListsnew();
            if (CollectionUtils.isNotEmpty(childLists)) {
                for (SkillNotes skillNotes : childLists) {
                    skillNotes.setUrl(mappingUrl + "/" + skillNotes.getIconValue());
                    if ("1".equals(skillNotes.getFalg() == null ? "" : skillNotes.getFalg().toString())) {
                        List<ResourceRelationDTO> resourceRelationInfo = systemResourceService.getResourceRelationInfo(Lists.newArrayList(Long.valueOf(skillNotes.getId())), Lists.newArrayList(16), null, 3);
                        skillNotes.setPathName(resourceRelationInfo.size() == 0 ? "" : resourceRelationInfo.get(0).getFileName());
                    }
                }
            }
        }
        return childLists;
    }


    @Override
    @Transactional
    public void saveOrUpdateSkill(List<SkillNotes> skillid) {
        try {
            if (CollectionUtils.isNotEmpty(skillid)) {
                deleteSkill(skillid.get(0).getId().intValue());
                insertSkillALL(skillid, null);
            } else {
                throw new BadRequestException("无数据修改");
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw new BadRequestException("保存失败");
        }
    }

    @Override
    public void updateSkill(Integer id, String name) {
        courseMapperExt.updateSkill(name, id, null);
    }

    public List<SkillNotes> querySkillCourse() {
        Long userId = userInfoHolder.getUserId();
        List<SkillNotes> list1 = Lists.newArrayList();
        List<Map<String, Object>> list = courseMapperExt.querySkillCourseInfonew(userId);
        if (CollectionUtils.isNotEmpty(list)) {
            for (Map<String, Object> map : list) {
                String courseid = map.get("id") == null ? "" : map.get("id").toString();
                String name = map.get("name") == null ? "" : map.get("name").toString();
                String iconValue = map.get("key_value") == null ? "" : map.get("key_value").toString();
                String isOwnCourse = map.get("is_own_course") == null ? "" : map.get("is_own_course").toString();
                SkillNotes skillNotes = new SkillNotes();
                skillNotes.setIconValue(iconValue);
                skillNotes.setCourseId(Integer.valueOf(courseid));
                skillNotes.setLevel(6);
                skillNotes.setName(name);
                skillNotes.setUrl(isOwnCourse);
                list1.add(skillNotes);
            }
        }
        return list1;
    }

    @Override
    public void insertOther(String iconValue, String name) {
        List<SkillDTO> list2 = courseMapperExt.querySkill(null, 1, name, "");
        if (list2 != null && list2.size() > 0) throw new BadRequestException("该岗位已存在");
        SkillNotes skillDTO = new SkillNotes();
        skillDTO.setName(name);
        skillDTO.setLevel(1);
        skillDTO.setIconValue(iconValue);
        courseMapperExt.insertSkill(skillDTO);
    }

    @Override
    public void deleteSkill(Integer skillid) {
        List<SkillNotes> childLists = courseMapperExt.getChildLists(skillid);
        List list = Lists.newArrayList();
        List list1 = Lists.newArrayList();
        if (childLists.get(0).getChildrenList() != null && childLists.get(0).getChildrenList().size() > 0) {
            list1 = queryIds(childLists, skillid, list);
        } else {
            list1.add(skillid);
        }
        courseMapperExt.deleteSkill(list1);
    }

    private List<Integer> queryIds(List<SkillNotes> childLists, Integer skillid, List list) {
        for (SkillNotes skillNotes : childLists) {
            list.add(skillNotes.getId());
            if (skillNotes.getChildrenList() != null && skillNotes.getChildrenList().size() > 0) {
                queryIds(skillNotes.getChildrenList(), skillid, list);
            }
        }
        return list;
    }

    @Transactional
    public void insertSkillALL(List<SkillNotes> childLists, Integer id) {
        Integer newid = null;
        for (SkillNotes skillNotes : childLists) {
            List<SkillNotes> childrenList = skillNotes.getChildrenList();
            if (skillNotes.getId() == null) {
                if (skillNotes.getParentId() == null) {
                    skillNotes.setParentId(id);
                }
            }
            id = courseMapperExt.insertSkill(skillNotes);
            newid = skillNotes.getId();
            if (CollectionUtils.isNotEmpty(childrenList)) {
                insertSkillALL(childrenList, newid);
            }
        }
    }

    public Map<String, List<SkillNotes>> querySkillOther(Integer id) {

        List<SkillNotes> childLists = courseMapperExt.getChildLists(id);
        if (childLists != null && childLists.size() > 0 && childLists.get(0).getChildrenList() != null && childLists.get(0).getChildrenList().size() > 0) {
            List<SkillNotes> childrenList = childLists.get(0).getChildrenList();
            List<SkillNotes> childrenList1 = childrenList.get(0).getChildrenList();
            Map map = new HashMap();
            Long userId = userInfoHolder.getUserId();
            String mappingUrl = LocalResourcesEnum.SYSTEM_FILE.getMappingUrl();
            for (SkillNotes skillNotes : childrenList1) {
                List<SkillNotes> list = Lists.newArrayList();
                if (skillNotes.getChildrenList().size() > 0) {
                    List<SkillNotes> skillNotes3 = querySkillInfoOther(skillNotes.getChildrenList());
                    for (SkillNotes skillNotes1 : skillNotes3) {
                        if (skillNotes1 != null && skillNotes1.getChildrenList().size() > 0 && skillNotes1.getChildrenList().get(0).getChildrenList().size() > 0) {
                            SkillNotes skillNotes2 = new SkillNotes();
                            String courseName = skillNotes1.getChildrenList().get(0).getChildrenList().size() == 0 ? "" : skillNotes1.getChildrenList().get(0).getChildrenList().get(0).getName();
                            List<CourseDTO> courseDTOS = queryTeacherCourse(userId);
                            courseDTOS.forEach(CourseDTO -> {
                                if (CourseDTO.getName().equals(courseName)) {
                                    skillNotes2.setCourseId(Integer.valueOf(CourseDTO.getId().toString()));
                                }

                            });
                            if (skillNotes2.getCourseId() == null || "".equals(skillNotes2.getCourseId())) {
                                List<Map<String, Object>> listmap = courseMapperExt.querySkillCourse(userId, skillNotes1.getChildrenList().get(0).getChildrenList().size() == 0 ? "" : skillNotes1.getChildrenList().get(0).getChildrenList().get(0).getName());
                                String idnew = "0";
                                String key_value = "";
                                if (listmap.size() > 1 && listmap != null) {
                                    for (Map<String, Object> map3 : listmap) {
                                        if ("1".equals(map3.get("is_own_course"))) {
                                            idnew = map3.get("id") == null ? "" : map3.get("id").toString();
                                        }
                                    }

                                } else if (listmap != null && listmap.size() == 1) {
                                    idnew = listmap.get(0).get("id") == null ? "" : listmap.get(0).get("id").toString();
                                }
                                skillNotes2.setCourseId(Integer.valueOf(idnew));
                            }
                            skillNotes2.setName(skillNotes1.getChildrenList().get(0).getChildrenList().size() == 0 ? "" : skillNotes1.getChildrenList().get(0).getChildrenList().get(0).getName());
                            skillNotes2.setIconValue(mappingUrl + "/" + (skillNotes1.getChildrenList().get(0).getChildrenList().size() == 0 ? "0" : skillNotes1.getChildrenList().get(0).getChildrenList().get(0).getIconValue()));
                            if (skillNotes2.getCourseId() != null && "0".equals(skillNotes2.getCourseId().toString())) {
                                skillNotes2.setIconValue(mappingUrl + "/" + "自定义课程.png");

                            }
                            list.add(skillNotes2);
                        }
                    }
                }
                map.put(skillNotes.getId(), list);

            }
            return map;
        }
        return null;
    }

    private List<SkillNotes> querySkillInfoOther(List<SkillNotes> skillNoteslist) {
        // 从list中索引为0开始往后遍历
        for (int i = 0; i < skillNoteslist.size() - 1; i++) {
            // 从list中索引为 list.size()-1 开始往前遍历
            for (int j = skillNoteslist.size() - 1; j > i; j--) {
                // 进行比较
                if (skillNoteslist.get(j).getChildrenList().size() > 0 && skillNoteslist.get(j).getChildrenList().get(0).getChildrenList().size() > 0 && skillNoteslist.get(i).getChildrenList().size() > 0 && skillNoteslist.get(i).getChildrenList().get(0).getChildrenList().size() > 0) {
                    if (skillNoteslist.get(j).getChildrenList().get(0).getChildrenList().get(0).getName().equals(skillNoteslist.get(i).getChildrenList().get(0).getChildrenList().get(0).getName())) {
                        // 去重
                        skillNoteslist.remove(j);
                    }
                }
            }
        }
        return skillNoteslist;
    }


    private void convertCourseBasic(CourseBasic courseBasic, CourseBasic param) {
        courseBasic.setName(param.getName());
        courseBasic.setIntroduction(param.getIntroduction());
        courseBasic.setType(param.getType());
        courseBasic.setIcon(param.getIcon());
        courseBasic.setUpdateTime(new Date());
        courseBasic.setImageLoadType(param.getImageLoadType());
    }

    private Map<Long, List<ClassCourseDTO>> queryCourseClassMap(List<CourseIndexInfoDTO> courses, Long userId) {

        if (CollectionUtils.isEmpty(courses)) return null;

        List<Long> courseIds = courses.stream().map(CourseIndexInfoDTO::getId).collect(Collectors.toList());

        // 获取助教的班级集合
        List<CourseTeacher> courseTeachers = queryCourseTeacher(courseIds, userId, null);
        Map<Long, List<CourseTeacher>> courseMap = BeanUtil.aggByKeyToList("courseId", courseTeachers);

        // 根据课程获取班级id集合
        List<ClassCourse> data = classService.listTeacherClass(userId, false, null, null);
        Map<Long, List<ClassCourse>> map = BeanUtil.aggByKeyToList("courseId", data);

        List<Long> classIds = data.stream().map(ClassCourse::getClassId).distinct().collect(Collectors.toList());
        classIds.addAll(courseTeachers.stream().map(CourseTeacher::getClassId).distinct().collect(Collectors.toList()));

        // 查询班级信息
        List<Class> classes = classService.listClass(classIds, null);
        Map<Long, Class> classMap = BeanUtil.mapByKey("id", classes);
        if (MapUtils.isEmpty(classMap)) return null;

        Map<Long, List<ClassCourseDTO>> courseClassMap = Maps.newHashMap();
        courseIds.forEach(courseId -> {
            List<ClassCourseDTO> classCourseDTOS = Lists.newArrayList();
            // 主讲教师的班级id集合
            if (MapUtils.isNotEmpty(map) && CollectionUtils.isNotEmpty(map.get(courseId))) {
                map.get(courseId).forEach(classCourse -> {
                    if (classMap.get(classCourse.getClassId()) == null) return;
                    ClassCourseDTO classCourseDTO = new ClassCourseDTO();
                    classCourseDTO.setId(classCourse.getClassId());
                    classCourseDTO.setGrade(classMap.get(classCourse.getClassId()).getGrade());
                    classCourseDTO.setEnded(false);
                    classCourseDTOS.add(classCourseDTO);
                });

            }
            // 助教的班级id集合
            if (MapUtils.isNotEmpty(courseMap) && CollectionUtils.isNotEmpty(courseMap.get(courseId))) {
                courseMap.get(courseId).forEach(courseTeacher -> {
                    if (classMap.get(courseTeacher.getClassId()) == null) return;
                    ClassCourseDTO classCourseDTO = new ClassCourseDTO();
                    classCourseDTO.setId(courseTeacher.getClassId());
                    classCourseDTO.setGrade(classMap.get(courseTeacher.getClassId()).getGrade());
                    classCourseDTO.setEnded(false);
                    classCourseDTOS.add(classCourseDTO);
                });
            }
            if (CollectionUtils.isNotEmpty(classCourseDTOS)) {
                courseClassMap.put(courseId, classCourseDTOS);
            }
        });

        return courseClassMap;

    }

    private List<CourseIndexInfoDTO> convertCourse(List<CourseDTO> courseDTOS) {
        List<CourseIndexInfoDTO> data = Lists.newArrayList();
        courseDTOS.forEach(courseDTO -> {
            CourseIndexInfoDTO info = new CourseIndexInfoDTO();
            info.setId(courseDTO.getId());
            info.setCourseBasicId(courseDTO.getCourseBasicId());
            info.setName(courseDTO.getName());
            info.setType(courseDTO.getType());
            info.setIcon(courseDTO.getIcon());
            info.setStatus(courseDTO.getStatus());
            info.setUserId(courseDTO.getUserId());
            info.setPreseted(courseDTO.getPreseted());
            info.setOwnCourse(false);
            data.add(info);
        });
        return data;
    }

    private List<CourseIndexInfoDTO> convertCourses(List<CourseDTO> courseDTOS) {
        List<CourseIndexInfoDTO> data = Lists.newArrayList();
        List<Long> courseBasicIds = Lists.newArrayList();
        List<Long> ids = Lists.newArrayList();
        courseDTOS.forEach(courseDTO -> {
            if (!ids.contains(courseDTO.getId()) && !courseBasicIds.contains(courseDTO.getCourseBasicId())) {
                CourseIndexInfoDTO info = new CourseIndexInfoDTO();
                info.setPreseted(courseDTO.getPreseted());
                info.setUserId(courseDTO.getUserId());
                info.setStatus(courseDTO.getStatus());
                info.setIcon(courseDTO.getIcon());
                info.setType(courseDTO.getType());
                info.setName(courseDTO.getName());
                info.setCourseBasicId(courseDTO.getCourseBasicId());
                info.setId(courseDTO.getId());
                info.setOwnCourse(courseDTO.getOwnCourse());
                info.setIconPath(courseDTO.getIconPath());
                info.setStatusValue(courseDTO.getStatusValue());
                info.setStudied(courseDTO.getStudied());
                info.setUserIds(courseDTO.getUserIds());
                data.add(info);
                courseBasicIds.add(courseDTO.getCourseBasicId());
                ids.add(courseDTO.getId());
            }
        });
        return data;
    }

}
